home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
editors
/
mjovesrc.zoo
/
extend.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-04
|
15KB
|
716 lines
/***************************************************************************
* This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
* is provided to you without charge, and with no warranty. You may give *
* away copies of JOVE, including sources, provided that this notice is *
* included in all the files. *
***************************************************************************/
#include "jove.h"
#include "fp.h"
#include "termcap.h"
#include "ctype.h"
#include "chars.h"
#include "disp.h"
#include "re.h"
#ifdef IPROCS
# include <signal.h>
#endif
#ifdef MAC
# include "mac.h"
#else
# ifdef STDARGS
# include <stdarg.h>
# else
# include <varargs.h>
# endif
#endif
#ifdef MSDOS
# include <process.h>
#endif
private void
DefAutoExec proto((struct data_obj *(*proc) ptrproto((const char *))));
private int
match proto((char **, char *));
int InJoverc = 0;
/* Auto execute code */
#define NEXECS 20
private struct {
char *a_pattern;
data_obj *a_cmd;
} AutoExecs[NEXECS]; /* must be initialized by system to 0 */
private int ExecIndex = 0;
/* Command auto-execute. */
void
CAutoExec()
{
DefAutoExec(findcom);
}
/* Macro auto-execute. */
void
MAutoExec()
{
DefAutoExec(findmac);
}
private void
DefAutoExec(proc)
data_obj *(*proc) ptrproto((const char *));
{
data_obj *d;
char *pattern;
int i;
if (ExecIndex >= NEXECS)
complain("Too many auto-executes, max %d.", NEXECS);
if ((d = (*proc)(ProcFmt)) == NULL)
return;
pattern = do_ask("\r\n", (bool (*) ptrproto((int))) NULL, (char *) NULL, ": %f %s ",
d->Name);
for (i = 0; i < ExecIndex; i++) {
if (AutoExecs[i].a_cmd == d) {
char *ipat = AutoExecs[i].a_pattern;
if ((pattern == NULL || ipat == NULL)?
(pattern == ipat) : (strcmp(pattern, ipat) == 0))
return; /* eliminate duplicates */
}
}
AutoExecs[ExecIndex].a_pattern = copystr(pattern);
AutoExecs[ExecIndex].a_cmd = d;
ExecIndex += 1;
}
/* DoAutoExec: NEW and OLD are file names, and if NEW and OLD aren't the
same kind of file (i.e., match the same pattern) or OLD is NULL and it
matches, OR if the pattern is NULL (none was specified) then, we execute
the command associated with that kind of file. */
void
DoAutoExec(new, old)
register char *new,
*old;
{
register int i;
set_arg_value(1);
for (i = 0; i < ExecIndex; i++)
if ((AutoExecs[i].a_pattern == NULL) ||
((new != NULL && LookingAt(AutoExecs[i].a_pattern, new, 0)) &&
(old == NULL || !LookingAt(AutoExecs[i].a_pattern, old, 0))))
ExecCmd(AutoExecs[i].a_cmd);
}
int
addgetc()
{
int c;
if (!InJoverc) {
Asking = YES;
AskingWidth = strlen(mesgbuf);
c = getch();
Asking = NO;
add_mess("%p ", c);
} else {
c = getch();
if (c == '\n')
return EOF; /* this isn't part of the sequence */
else if (c == '\\') {
if ((c = getch()) == LF)
complain("[Premature end of line]");
} else if (c == '^') {
if ((c = getch()) == '?')
c = RUBOUT;
else if (jisalpha(c) || strchr("@[\\]^_", c))
c = CTL(c);
else
complain("[Unknown control character]");
}
}
return c;
}
void
Extend()
{
data_obj *d;
if ((d = findcom(": ")) != NULL)
ExecCmd(d);
}
/* Read a positive integer from CP. It must be in base BASE, and
complains if it isn't. If allints is nonzero, all the characters
in the string must be integers or we return -1; otherwise we stop
reading at the first nondigit. */
int
chr_to_int(cp, base, allints, result)
register char *cp;
int base,
allints;
register int *result;
{
register int c;
int value = 0,
sign;
if ((c = *cp) == '-') {
sign = -1;
cp += 1;
} else
sign = 1;
while ((c = *cp++) != '\0') {
if (!jisdigit(c)) {
if (allints == YES)
return INT_BAD;
break;
}
c = c - '0';
if (c >= base)
complain("You must specify in base %d.", base);
value = value * base + c;
}
*result = value * sign;
return INT_OKAY;
}
int
ask_int(prompt, base)
char *prompt;
int base;
{
char *val = ask((char *)NULL, prompt);
int value;
if (chr_to_int(val, base, YES, &value) == INT_BAD)
complain("That's not a number!");
return value;
}
void
vpr_aux(vp, buf, size)
register const struct variable *vp;
char *buf;
size_t size;
{
switch (vp->v_flags & V_TYPEMASK) {
case V_BASE10:
swritef(buf, size, "%d", *((int *) vp->v_value));
break;
case V_BASE8:
swritef(buf, size, "%o", *((int *) vp->v_value));
break;
case V_BOOL:
swritef(buf, size, (*((int *) vp->v_value)) ? "on" : "off");
break;
case V_STRING:
case V_FILENAME:
swritef(buf, size, "%s", vp->v_value);
break;
case V_CHAR:
swritef(buf, size, "%p", *((int *) vp->v_value));
break;
}
}
void
PrVar()
{
struct variable *vp;
char prbuf[256];
if ((vp = (struct variable *) findvar(ProcFmt)) == NULL)
return;
vpr_aux(vp, prbuf, sizeof(prbuf));
s_mess(": %f %s => %s", vp->Name, prbuf);
}
void
SetVar()
{
struct variable *vp;
char prompt[128];
if ((vp = (struct variable *) findvar(ProcFmt)) == NULL)
return;
swritef(prompt, sizeof(prompt), ": %f %s ", vp->Name);
switch (vp->v_flags & V_TYPEMASK) {
case V_BASE10:
case V_BASE8:
*((int *) vp->v_value) = ask_int(prompt,
((vp->v_flags & V_TYPEMASK) == V_BASE10)? 10 : 8);
break;
case V_BOOL:
{
char *def = *((bool *) vp->v_value) ? "off" : "on",
*on_off;
bool value;
on_off = ask(def, prompt);
if (casecmp(on_off, "on") == 0)
value = ON;
else if (casecmp(on_off, "off") == 0)
value = OFF;
else {
complain("Boolean variables must be ON or OFF.");
/* NOTREACHED */
}
*((bool *) vp->v_value) = value;
#ifdef MAC
MarkVar(vp,-1,0); /* mark the menu item */
#endif
s_mess("%s%s", prompt, value ? "on" : "off");
break;
}
case V_FILENAME:
{
char fbuf[FILESIZE];
size_t pl = strlen(prompt);
swritef(&prompt[pl], sizeof(prompt)-pl, "(default %s) ",
(char *)vp->v_value);
(void) ask_file(prompt, (char *) vp->v_value, fbuf);
strcpy((char *) vp->v_value, fbuf);
break;
}
case V_STRING:
{
char *str;
/* Do_ask() so you can set string to "" if you so desire. */
str = do_ask("\r\n", (bool (*) ptrproto((int))) NULL,
(char *) vp->v_value, prompt);
if (str == NULL)
str = NullStr;
strcpy((char *) vp->v_value, str);
/* ... and hope there is enough room. */
break;
}
case V_CHAR:
f_mess(prompt);
*((int *) vp->v_value) = addgetc();
break;
}
if (vp->v_flags & V_MODELINE)
UpdModLine = YES;
if (vp->v_flags & V_CLRSCREEN) {
#ifdef IBMPC
setcolor(Fgcolor, Bgcolor);
#endif /* IBMPC */
ClAndRedraw();
}
if (vp->v_flags & V_TTY_RESET)
tty_reset();
}
/* Command completion - possible is an array of strings, prompt is
the prompt to use, and flags are ... well read jove.h.
If flags are RET_STATE, and the user hits <return> what they typed
so far is in the Minibuf string. */
private char **Possible;
private int comp_value,
comp_flags;
private bool
aux_complete(c)
int c;
{
int command,
i;
if (comp_flags & CASEIND) {
char *lp;
for (lp = linebuf; *lp != '\0'; lp++)
if (jisupper(*lp))
*lp = jtolower(*lp);
}
switch (c) {
case EOF:
comp_value = -1;
return FALSE;
case '\r':
case '\n':
command = match(Possible, linebuf);
if (command >= 0) {
comp_value = command;
return FALSE; /* tells ask to stop */
}
if (eolp() && bolp()) {
comp_value = NULLSTRING;
return FALSE;
}
if (comp_flags & RET_STATE) {
comp_value = command;
return FALSE;
}
if (InJoverc)
complain("[\"%s\" unknown]", linebuf);
rbell();
break;
case '\t':
case ' ':
{
int minmatch = 1000,
maxmatch = 0,
numfound = 0,
lastmatch = -1,
len = strlen(linebuf);
for (i = 0; Possible[i] != 0; i++) {
int this_len;
this_len = numcomp(Possible[i], linebuf);
maxmatch = max(maxmatch, this_len);
if (this_len >= len) {
if (numfound)
minmatch = min(minmatch, numcomp(Possible[lastmatch], Possible[i]));
else
minmatch = strlen(Possible[i]);
numfound += 1;
lastmatch = i;
if (strcmp(linebuf, Possible[i]) == 0)
break;
}
}
if (numfound == 0) {
rbell();
if (InJoverc)
compl